package com.gadgets.framework.common.util;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

/**
 * @author UncleXiu
 * @version V1.0.0
 * @data 2020-09-21
 *
 */
public class HttpClientUtil {

    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    /**
     * HTTP请求配置信息<br/>
     * 连接超时时间30s<br/>
     * 请求超时时间60s<br/>
     * Socket传输超时时间120s<br/>
     * 允许重定向<br/>
     */
    private static final RequestConfig config = RequestConfig.custom()
            .setConnectTimeout(10*1000)
            .setConnectionRequestTimeout(20*1000)
            .setSocketTimeout(120*1000)
            .setRedirectsEnabled(true)
            .build();

    /**
     * 通过Get方法请求HTTP
     * （通用返回）
     * @param headers       HTTP头
     * @param url           请求地址
     * @return              通用应答
     */
    protected static CloseableHttpResponse requestHttpByGetMethod(HashMap<String,String> headers, String url){
        CloseableHttpClient closeableHttpClient = null;
        if(url.startsWith("https")){
            try {
                SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                    //信任所有
                    public boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {
                        return true;
                    }
                }).build();
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
                closeableHttpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
                logger.error(StringUtils.formatExceptionStack(e));
                closeableHttpClient = HttpClients.createDefault();
            }
        }else {
            closeableHttpClient = HttpClientBuilder.create().build();
        }
        HttpGet httpGet = new HttpGet(url);
        if(null!=headers && headers.size()>0){
            for (Map.Entry<String, String> head : headers.entrySet()) {
                httpGet.addHeader(head.getKey(),head.getValue());
            }
        }
        httpGet.setConfig(config);
        CloseableHttpResponse response = null;
        try {
            response = closeableHttpClient.execute(httpGet);
            return response;
        } catch (IOException e) {
            logger.error("地址{}请求失败",url);
            logger.error(StringUtils.formatExceptionStack(e));
        }
        return null;
    }

    /**
     * 通过Get方法请求HTTP
     * （文本返回）
     * @param headers   HTTP头
     * @param url       请求地址
     * @param encoding  应答编码集
     * @return          通用应答
     */
    public static String requestHttpByGetMethodForTxt(HashMap<String,String> headers, String url, String encoding){
        CloseableHttpResponse response = requestHttpByGetMethod(headers, url);
        if(null!=response) {
            try {
                return EntityUtils.toString(response.getEntity(),encoding);
            } catch (IOException e) {
                logger.error("获取响应结果失败");
                logger.error(StringUtils.formatExceptionStack(e));
            } finally {
                try {
                    response.close();
                } catch (IOException e) {
                    logger.error("关闭请求请求客户端失败");
                    logger.error(StringUtils.formatExceptionStack(e));
                }
            }
        }
        return null;
    }

    /**
     * 通过Get方法请求HTTP
     * （字节返回）
     * @param headers   HTTP头
     * @param url       请求地址
     * @return          通用应答
     */
    public static byte[] requestHttpByGetMethodForByte(HashMap<String,String> headers, String url){
        CloseableHttpResponse response = requestHttpByGetMethod(headers, url);
        if(null!=response) {
            try {
                return EntityUtils.toByteArray(response.getEntity());
            } catch (IOException e) {
                logger.error("获取响应结果失败");
                logger.error(StringUtils.formatExceptionStack(e));
            } finally {
                try {
                    response.close();
                } catch (IOException e) {
                    logger.error("关闭请求请求客户端失败");
                    logger.error(StringUtils.formatExceptionStack(e));
                }
            }
        }
        return null;
    }

}
